package com.springboot.ball.consumer;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.springboot.ball.consumer.games.Game;
import com.springboot.ball.consumer.games.Player;
import com.springboot.ball.consumer.utils.JwtAuthentication;
import com.springboot.ball.mapper.ChatMessageMapper;
import com.springboot.ball.mapper.UserMapper;
import com.springboot.ball.pojo.ChatMessage;
import com.springboot.ball.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;


import java.io.IOException;
import java.time.LocalDateTime;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
@ServerEndpoint("/websocket/{token}")  // 注意不要以'/'结尾
public class WebSocketServer {

    final public static ConcurrentHashMap<Integer, WebSocketServer> users = new ConcurrentHashMap<>();
    private User user;
    private Session session = null;
    final private static CopyOnWriteArraySet<User> matchpool = new CopyOnWriteArraySet<>();
    public static UserMapper userMapper;
    private static ChatMessageMapper chatMessageMapper;
    private static RestTemplate restTemplate;
    private Game game=null;
    private final static String addPlayerUrl = "http://ball-matchingsystem:3001/player/add/";
    private final static String removePlayerUrl = "http://ball-matchingsystem:3001/player/remove/";

    // 游戏配置参数，可以根据需要调整
    private static final int DEFAULT_WIDTH = 1000;
    private static final int DEFAULT_HEIGHT = 600;
    private static final double DEFAULT_PLAYER_RADIUS = 40.0;
    private static final double DEFAULT_PLAYER_SPEED = 80.0;  // 从60.0提高到80.0，使玩家移动更快速，游戏更流畅

    // 用于存储玩家上次治疗的时间戳
    private static final ConcurrentHashMap<Integer, Long> lastHealTimestamps = new ConcurrentHashMap<>();
    // 治疗技能冷却时间(毫秒)
    private static final long HEAL_COOLDOWN = 10000; // 10秒

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        WebSocketServer.restTemplate = restTemplate;
    }

    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        WebSocketServer.userMapper = userMapper;
    }

    @Autowired
    public void setChatMessageMapper(ChatMessageMapper chatMessageMapper) {
        WebSocketServer.chatMessageMapper = chatMessageMapper;
    }

    private void saveMessage(JSONObject data) {
        ChatMessage message = new ChatMessage();
        message.setFromUserId(this.user.getId());
        message.setToUserId(data.getInteger("to"));
        message.setContent(data.getString("content"));
        message.setCreateTime(LocalDateTime.now());
        log.info("保存聊天内容: {}", message);
        chatMessageMapper.insert(message);//保存聊天内容到数据库
    }

    private void broadcastOnlineUsers() {
        JSONObject message = new JSONObject();
        message.put("event", "online-users");
        JSONArray usersList = new JSONArray();
        for (WebSocketServer server : users.values()) {
            if (server.user != null) {
                User u = server.user;
                JSONObject userJson = new JSONObject();
                userJson.put("id", u.getId());
                userJson.put("username", u.getUsername());
                userJson.put("photo", u.getPhoto());
                usersList.add(userJson);
            }
        }
        message.put("users", usersList);
        String msg = message.toJSONString();

        // 为了避免并发问题，创建一个用户列表的副本然后遍历
        java.util.ArrayList<WebSocketServer> serversCopy = new java.util.ArrayList<>(users.values());
        for (WebSocketServer server : serversCopy) {
            try {
                if (server != null && server.session != null && server.session.isOpen()) {
                    server.sendMessage(msg);
                }
            } catch (Exception e) {
                log.error("广播在线用户时出错: {}", e.getMessage());
            }
        }
    }

    // 在类内添加消息处理方法
    private void handlePrivateMessage(JSONObject data) {
        int toUserId = data.getInteger("to");
        String content = data.getString("content");

        WebSocketServer target = users.get(toUserId);
        if (target != null && target.session.isOpen()) {
            // 发送消息通知
            JSONObject notification = new JSONObject();
            notification.put("event", "new-message");
            notification.put("from", this.user.getId());
            notification.put("fromName", this.user.getUsername());
            notification.put("content", content);
            notification.put("timestamp", System.currentTimeMillis());
            target.sendMessage(notification.toJSONString());

            JSONObject message = new JSONObject();
            message.put("event", "private-message");
            message.put("from", this.user.getId());
            message.put("fromName", this.user.getUsername());
            message.put("content", content);
            message.put("timestamp", System.currentTimeMillis());
            // 发送消息到发送者
            target.sendMessage(message.toJSONString());
        }
    }
    private void sendHistoryMessage(Integer from, Integer to) {
        List<ChatMessage> messages = chatMessageMapper.selectHistory(from, to);
        JSONObject event = new JSONObject();
        event.put("event", "history-message");
        event.put("messages", messages);
        sendMessage(event.toJSONString());
    }

    // 发送好友请求通知
    public static void sendFriendRequest(Integer fromUserId, Integer toUserId) {
        WebSocketServer target = users.get(toUserId);
        if (target != null) {
            User fromUser = userMapper.selectById(fromUserId);
            JSONObject message = new JSONObject();
            message.put("event", "friend-request");

            message.put("fromUserId", fromUserId);
            message.put("fromUsername", fromUser.getUsername());
            message.put("fromUserPhoto", fromUser.getPhoto());
            message.put("createTime", LocalDateTime.now().toString());
            target.sendMessage(message.toJSONString());
        }
    }
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) throws IOException {
        //  建立连接时自动调用
        this.session = session;
        log.info("connect!");
        int userId = JwtAuthentication.getUserId(token);
        this.user = userMapper.selectById(userId);
        if (this.user != null) {
            users.put(userId, this);
            broadcastOnlineUsers(); // 新增：广播在线用户列表
        } else {
            this.session.close();
        }
        System.out.println(users);
    }

    @OnClose
    public void onClose() {
        // 关闭链接时自动调用
        log.info("WebSocket连接关闭: 用户ID={}", user != null ? user.getId() : "未登录");

        // 如果用户在游戏中，先处理游戏结束
        if (user != null && game != null) {
            log.info("用户 {} 在游戏中断开连接，处理游戏结束", user.getId());
            
            // 调用handleEndGame方法确保处理游戏结束逻辑
            try {
                handleEndGame();
                log.info("已处理用户 {} 的游戏结束逻辑", user.getId());
            } catch (Exception e) {
                log.error("处理用户 {} 游戏结束时出错: {}", user.getId(), e.getMessage());
            }
        }

        if (user != null) {
            users.remove(this.user.getId());
            matchpool.remove(this.user);
            broadcastOnlineUsers(); // 新增：广播在线用户列表
            log.info("已从在线用户列表和匹配池中移除用户 {}", user.getId());
        }
    }
    public static void startGame(Integer aId, Integer bId, Integer cId) {
        User user1 = userMapper.selectById(aId);
        User user2 = userMapper.selectById(bId);
        User user3 = userMapper.selectById(cId);

        // 创建游戏对象，传递参数而不是使用固定值
        Game game = new Game(user1.getId(), user2.getId(), user3.getId(),
                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_PLAYER_RADIUS, DEFAULT_PLAYER_SPEED);

        if(users.get(user1.getId())!=null)
            users.get(user1.getId()).game = game;
        if(users.get(user2.getId())!=null)
            users.get(user2.getId()).game = game;
        if(users.get(user3.getId())!=null)
            users.get(user3.getId()).game = game;

        game.start();

        JSONObject respGame = new JSONObject();
        respGame.put("a_id", game.getPlayerA().getId());
        respGame.put("b_id", game.getPlayerB().getId());
        respGame.put("c_id", game.getPlayerC().getId());
        respGame.put("a_x", game.getPlayerA().getX());
        respGame.put("b_x", game.getPlayerB().getX());
        respGame.put("c_x", game.getPlayerC().getX());
        respGame.put("a_y", game.getPlayerA().getY());
        respGame.put("b_y", game.getPlayerB().getY());
        respGame.put("c_y", game.getPlayerC().getY());
        respGame.put("a_radius", game.getPlayerA().getRadius());
        respGame.put("b_radius", game.getPlayerB().getRadius());
        respGame.put("c_radius", game.getPlayerC().getRadius());
        respGame.put("a_speed", game.getPlayerA().getSpeed());
        respGame.put("b_speed", game.getPlayerB().getSpeed());
        respGame.put("c_speed", game.getPlayerC().getSpeed());

        // 给user1发送两个对手的信息
        JSONObject resp1 = new JSONObject();
        resp1.put("event", "start-matching");
        resp1.put("opponent1_id", user2.getId());
        resp1.put("opponent1_username", user2.getUsername());
        resp1.put("opponent1_photo", user2.getPhoto());
        resp1.put("opponent2_id", user3.getId());
        resp1.put("opponent2_username", user3.getUsername());
        resp1.put("opponent2_photo", user3.getPhoto());
        resp1.put("game", respGame);
        if(users.get(user1.getId())!=null)
            users.get(user1.getId()).sendMessage(resp1.toJSONString());

        // 给user2发送两个对手的信息
        JSONObject resp2 = new JSONObject();
        resp2.put("event", "start-matching");
        resp2.put("opponent1_id", user1.getId());
        resp2.put("opponent1_username", user1.getUsername());
        resp2.put("opponent1_photo", user1.getPhoto());
        resp2.put("opponent2_id", user3.getId());
        resp2.put("opponent2_username", user3.getUsername());
        resp2.put("opponent2_photo", user3.getPhoto());
        resp2.put("game", respGame);
        if(users.get(user2.getId())!=null)
            users.get(user2.getId()).sendMessage(resp2.toJSONString());

        // 给user3发送两个对手的信息
        JSONObject resp3 = new JSONObject();
        resp3.put("event", "start-matching");
        resp3.put("opponent1_id", user1.getId());
        resp3.put("opponent1_username", user1.getUsername());
        resp3.put("opponent1_photo", user1.getPhoto());
        resp3.put("opponent2_id", user2.getId());
        resp3.put("opponent2_username", user2.getUsername());
        resp3.put("opponent2_photo", user2.getPhoto());
        resp3.put("game", respGame);
        if(users.get(user3.getId())!=null)
            users.get(user3.getId()).sendMessage(resp3.toJSONString());
    }

    private void startMatching() {
        System.out.println("startMatching");
        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
        data.add("user_id",this.user.getId().toString());
        data.add("rating",this.user.getRating().toString());
        restTemplate.postForObject(addPlayerUrl, data, String.class);
    }

    private void stopMatching() {
        System.out.println("stopMatching");
        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
        data.add("user_id",this.user.getId().toString());
        restTemplate.postForObject(removePlayerUrl,data,String.class);
    }

    // 更新move方法，处理前端发送的移动事件
    private void move(JSONObject data) {
        // 检查参数是否完整
        if (!data.containsKey("userId") || !data.containsKey("x") || !data.containsKey("y")
                || !data.containsKey("tx") || !data.containsKey("ty")) {
            log.error("移动事件缺少必要参数: {}", data);
            return;
        }

        Integer userId = data.getInteger("userId");
        double x = data.getDouble("x");
        double y = data.getDouble("y");
        double tx = data.getDouble("tx");
        double ty = data.getDouble("ty");

        log.info("玩家 {} 移动: 当前位置({}, {}), 目标位置({}, {})", userId, x, y, tx, ty);

        // 修改为简单地广播移动事件给所有玩家
        if (game != null) {
            // 广播给游戏中的所有玩家
            JSONObject moveEvent = new JSONObject();
            moveEvent.put("event", "move");
            moveEvent.put("userId", userId);
            moveEvent.put("x", x);
            moveEvent.put("y", y);
            moveEvent.put("tx", tx);
            moveEvent.put("ty", ty);

            game.sendAllMessage(moveEvent.toJSONString());
            log.info("广播玩家 {} 的移动事件", userId);
        }
    }

    // 更新handleFireBall方法，处理前端发送的火球事件
    private void handleFireBall(JSONObject data) {
        // 检查参数是否完整
        if (!data.containsKey("userId") || !data.containsKey("x") || !data.containsKey("y")
                || !data.containsKey("tx") || !data.containsKey("ty")) {
            log.error("火球事件缺少必要参数: {}", data);
            return;
        }

        Integer userId = data.getInteger("userId");
        double x = data.getDouble("x");
        double y = data.getDouble("y");
        double tx = data.getDouble("tx");
        double ty = data.getDouble("ty");

        log.info("玩家 {} 发射火球: 起始位置({}, {}), 目标位置({}, {})", userId, x, y, tx, ty);

        if (game != null) {
            // 广播给游戏中的所有玩家
            JSONObject fireballEvent = new JSONObject();
            fireballEvent.put("event", "shoot-fireball");
            fireballEvent.put("userId", userId);
            fireballEvent.put("x", x);
            fireballEvent.put("y", y);
            fireballEvent.put("tx", tx);
            fireballEvent.put("ty", ty);

            game.sendAllMessage(fireballEvent.toJSONString());
            log.info("广播玩家 {} 的发射火球事件", userId);
        }
    }
    //处理闪现技能
    private void handlePlayerFlash(JSONObject data){
        // 获取必要参数
        Integer userId = data.getInteger("userId");
        double x = data.containsKey("x") ? data.getDouble("x") : 0.5; // 当前位置X
        double y = data.containsKey("y") ? data.getDouble("y") : 0.5; // 当前位置Y
        double tx = data.getDouble("tx"); // 目标位置X
        double ty = data.getDouble("ty"); // 目标位置Y
        
        // 计算最大闪现距离（地图高度的30%）
        double maxDistance = DEFAULT_HEIGHT * 0.3 / DEFAULT_HEIGHT;
        
        // 计算闪现实际距离和角度
        double dx = tx - x;
        double dy = ty - y;
        double distance = Math.sqrt(dx * dx + dy * dy);
        
        // 限制最大闪现距离
        if (distance > maxDistance) {
            // 按比例缩放目标位置
            double ratio = maxDistance / distance;
            tx = x + dx * ratio;
            ty = y + dy * ratio;
            distance = maxDistance;
        }
        
        // 构建广播消息
        JSONObject flashEvent = new JSONObject();
        flashEvent.put("event", "flash");
        flashEvent.put("userId", userId);
        flashEvent.put("x", x);
        flashEvent.put("y", y);
        flashEvent.put("tx", tx);
        flashEvent.put("ty", ty);
        flashEvent.put("newX", tx);  // 添加实际落点坐标
        flashEvent.put("newY", ty);  // 添加实际落点坐标
        
        if (game != null) {
            // 广播给游戏中的所有玩家
            game.sendAllMessage(flashEvent.toJSONString());
            log.info("广播玩家 {} 的闪现事件", userId);
        }
    }

    private void handlePlayerHeal(JSONObject data){
        // 获取玩家ID（从当前WebSocket会话）
        Integer userId = this.user.getId();
        
        // 检查冷却时间
        long currentTime = System.currentTimeMillis();
        Long lastHealTime = lastHealTimestamps.get(userId);
        
        if (lastHealTime != null) {
            long elapsedTime = currentTime - lastHealTime;
            if (elapsedTime < HEAL_COOLDOWN) {
                // 如果冷却时间未到，返回冷却状态消息
                JSONObject cooldownResponse = new JSONObject();
                cooldownResponse.put("event", "heal-cooldown");
                cooldownResponse.put("remaining", (HEAL_COOLDOWN - elapsedTime) / 1000.0); // 剩余秒数
                this.sendMessage(cooldownResponse.toJSONString());
                log.info("玩家 {} 尝试治疗但技能在冷却中，剩余冷却时间: {}秒", 
                    userId, (HEAL_COOLDOWN - elapsedTime) / 1000.0);
                return;
            }
        }
        
        // 治疗量（可根据游戏平衡性调整，这里假设为30%最大生命值）
        int healAmount = 30;
        
        // 检查玩家是否在游戏中
        if (game != null) {
            // 查找玩家当前血量
            Integer playerId = userId;
            Player player = game.getPlayerA().getId().equals(playerId) ? game.getPlayerA() :
                           game.getPlayerB().getId().equals(playerId) ? game.getPlayerB() :
                           game.getPlayerC().getId().equals(playerId) ? game.getPlayerC() : null;
                           
            if (player != null) {
                // 更新血量（不超过最大值）
                double currentHp = player.getHealth();
                double newHp = Math.min(100, currentHp + healAmount);
                player.setHealth(newHp);
                
                // 更新上次治疗时间
                lastHealTimestamps.put(userId, currentTime);
                
                // 构建广播消息
                JSONObject healEvent = new JSONObject();
                healEvent.put("event", "heal");
                healEvent.put("userId", userId);
                healEvent.put("hp", newHp);
                healEvent.put("amount", healAmount);
                healEvent.put("cooldownMs", HEAL_COOLDOWN); // 添加冷却时间信息
                
                // 广播给游戏中的所有玩家
                game.sendAllMessage(healEvent.toJSONString());
                log.info("广播玩家 {} 的治疗事件，恢复血量 {}，当前血量 {}", userId, healAmount, newHp);
            } else {
                log.warn("玩家 {} 尝试治疗但不在当前游戏中", userId);
            }
        } else {
            log.warn("玩家 {} 尝试治疗但当前没有活跃游戏", userId);
        }
    }

    // 处理火球命中事件
    private void handleFireballHit(JSONObject data) {
        // 检查参数是否完整
        if (!data.containsKey("attackerId") || !data.containsKey("targetId")
                || !data.containsKey("fireballX") || !data.containsKey("fireballY") || !data.containsKey("hitId")) {
            log.error("火球命中事件缺少必要参数: {}", data);
            return;
        }

        Integer attackerId = data.getInteger("attackerId");
        Integer targetId = data.getInteger("targetId");
        double fireballX = data.getDouble("fireballX");
        double fireballY = data.getDouble("fireballY");
        String hitId = data.getString("hitId");

        log.info("处理火球命中: 攻击者={}, 目标={}, 火球位置=({}, {}), 命中ID={}",
                attackerId, targetId, fireballX, fireballY, hitId);

        if (game != null) {
            // 获取目标玩家并计算伤害
            Player targetPlayer = game.getPlayerById(targetId);
            if (targetPlayer != null && targetPlayer.isAlive()) {
                // 计算伤害值 - 这里使用Game中定义的fireballDamage
                double damage = game.getFireballDamage();
                // 更新玩家生命值
                double currentHealth = targetPlayer.getHealth();
                double remainingHealth = Math.max(0, currentHealth - damage);
                targetPlayer.setHealth(remainingHealth);

                log.info("玩家 {} 被击中, 当前血量: {} -> {}", targetId, currentHealth, remainingHealth);

                // 创建命中消息并广播
                JSONObject hitEvent = new JSONObject();
                hitEvent.put("event", "fireball-hit");
                hitEvent.put("attackerId", attackerId);
                hitEvent.put("playerId", targetId); // 目标玩家ID
                hitEvent.put("remainingHp", remainingHealth);
                hitEvent.put("fireballX", fireballX);
                hitEvent.put("fireballY", fireballY);
                hitEvent.put("hitId", hitId);

                game.sendAllMessage(hitEvent.toJSONString());
                log.info("广播火球命中事件: 玩家 {} 被 {} 击中, 剩余血量 {}", targetId, attackerId, remainingHealth);
                
              if(remainingHealth <= 0){
                  if(game.getPlayerA().getId().equals(targetId)){
                      game.playerDeath("A");
                  }else if(game.getPlayerB().getId().equals(targetId)){
                      game.playerDeath("B");
                  }else if(game.getPlayerC().getId().equals(targetId)){
                      game.playerDeath("C");
                  }
                  
                  // 强制检查游戏结果，确保玩家死亡后立即判断游戏是否结束
                  game.checkGameResult();
                  log.info("火球击杀玩家后检查游戏结果，当前状态: {}", game.getStatus());
              }
            } else {
                log.warn("目标玩家 {} 不存在或已死亡，忽略火球命中", targetId);
            }
        }
    }
    // 处理玩家死亡
    private void handlePlayerDeath(JSONObject data) {
        if (game == null) {
            log.warn("收到玩家死亡事件，但当前无活跃游戏");
            return;
        }

        // 检查参数完整性
        if (!data.containsKey("playerId")) {
            log.error("处理玩家死亡事件失败: 缺少必要参数 playerId");
            return;
        }
        
        Integer playerId = data.getInteger("playerId");
        if (playerId == null) {
            log.error("处理玩家死亡事件失败: playerId 为空");
            return;
        }
        
        // 调用通用方法处理玩家死亡
        processPlayerDeath(playerId, "player-death");
    }

    // 添加处理游戏结束的方法
    private void handleEndGame() {
        if (game == null) {
            log.warn("用户 {} 尝试结束游戏，但游戏对象为null", this.user.getId());
            return;
        }

        log.info("用户 {} 主动结束游戏", this.user.getId());

        // 如果游戏还在进行中，可能需要处理一些清理工作
        if ("playing".equals(game.getStatus())) {
            // 处理当前用户作为玩家的死亡
            processPlayerDeath(this.user.getId(), "player_quit");
        } else {
            log.info("游戏已经不在进行中状态: {}", game.getStatus());
        }
        
        // 清空当前用户的游戏引用
        this.game = null;
    }

    // 抽取公共逻辑处理玩家死亡
    private void processPlayerDeath(Integer playerId, String reason) {
        if (game == null) return;
        
        log.info("处理玩家 {} 的死亡事件，原因: {}", playerId, reason);
        
        // 确定是哪个玩家
        String playerIdentifier = null;
        Player playerToSet = null;
        
        if (game.getPlayerA() != null && game.getPlayerA().getId().equals(playerId)) {
            playerIdentifier = "A";
            playerToSet = game.getPlayerA();
            // 检查玩家是否已经死亡
            if (!game.getPlayerA().isAlive()) {
                log.info("玩家 {}(A) 已经是死亡状态，忽略重复处理", playerId);
                return;
            }
        } else if (game.getPlayerB() != null && game.getPlayerB().getId().equals(playerId)) {
            playerIdentifier = "B";
            playerToSet = game.getPlayerB();
            // 检查玩家是否已经死亡
            if (!game.getPlayerB().isAlive()) {
                log.info("玩家 {}(B) 已经是死亡状态，忽略重复处理", playerId);
                return;
            }
        } else if (game.getPlayerC() != null && game.getPlayerC().getId().equals(playerId)) {
            playerIdentifier = "C";
            playerToSet = game.getPlayerC();
            // 检查玩家是否已经死亡
            if (!game.getPlayerC().isAlive()) {
                log.info("玩家 {}(C) 已经是死亡状态，忽略重复处理", playerId);
                return;
            }
        }
        
        if (playerIdentifier == null) {
            log.error("无法识别玩家 {} 的身份标识", playerId);
            return;
        }
        
        try {
            // 确保玩家标记为死亡状态
            if (playerToSet != null) {
                playerToSet.kill();
            }
            
            // 调用Game中的playerDeath方法处理死亡
            log.info("设置玩家 {}({}) 为死亡状态", playerId, playerIdentifier);
            game.playerDeath(playerIdentifier);
            
            // 广播死亡消息给所有客户端
            JSONObject deathEvent = new JSONObject();
            deathEvent.put("event", "player_death");
            deathEvent.put("player_id", playerId);
            deathEvent.put("identifier", playerIdentifier);
            if (reason != null && !reason.isEmpty()) {
                deathEvent.put("reason", reason);
            }
            game.sendAllMessage(deathEvent.toJSONString());
            
            // 强制检查游戏结果
            game.checkGameResult();
            log.info("玩家死亡事件处理完成，当前游戏状态: {}", game.getStatus());
        } catch (Exception e) {
            log.error("处理玩家 {} 死亡事件时出错: {}", playerId, e.getMessage());
        }
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        JSONObject data = JSONObject.parseObject(message);
        String event = data.getString("event");

        log.info("收到WebSocket消息: event={}, data={}", event, message);

        switch (event) {
            case "start-matching":
                startMatching();
                break;
            case "stop-matching":
                stopMatching();
                break;
            case "private-message":
                saveMessage(data);
                handlePrivateMessage(data);
                break;
            case "friend-request":
                sendFriendRequest(user.getId(), data.getInteger("toUserId"));
                break;
            case "friend-update":
                sendFriendUpdate(user.getId(), data.getInteger("toUserId"), data.getString("status"));
                break;
            case "get-history":
                sendHistoryMessage(
                        data.getInteger("from"),
                        data.getInteger("to")
                );
                break;
            case "move":
                move(data);
                break;
            case "shoot-fireball":
                handleFireBall(data);
                break;
            case"heal":
                handlePlayerHeal(data);
                break;
            case "flash":
                handlePlayerFlash(data);
                break;
            case "fireball-hit":
                handleFireballHit(data);
                break;
            case "player-death":  // 处理前端发送的player-death事件
                log.info("接收到前端发送的player-death事件");
                handlePlayerDeath(data);
                break;
            case "end-game":
                log.info("接收到前端发送的end-game事件: {}", data);
                handleEndGame();
                break;
            case "game-invite":
                sendGameInvitation(user.getId(), data.getInteger("toUserId"));
                break;
            case "game-invite-response":
                handleGameInviteResponse(data);
                break;
            case "ping":  // 增加对ping消息的支持
                // 简单返回pong消息，用于连接测试
                JSONObject pongResponse = new JSONObject();
                pongResponse.put("event", "pong");
                pongResponse.put("timestamp", System.currentTimeMillis());
                this.sendMessage(pongResponse.toJSONString());
                break;
            default:
                log.warn("收到未知类型的WebSocket消息: {}", event);
                break;
        }
    }


    // 新增通知方法
    public static void sendFriendUpdate(Integer user1, Integer user2, String status) {
        notifyUser(user1, status);
        notifyUser(user2, status);
    }

    private static void notifyUser(Integer fromUserId, String status) {
        WebSocketServer target = users.get(fromUserId);
        if (target != null) {
            JSONObject msg = new JSONObject();
            msg.put("event", "friend-update");
            msg.put("status", status);
            target.sendMessage(msg.toJSONString());
        }
    }

    // 发送游戏邀请
    public static void sendGameInvitation(Integer fromUserId, Integer toUserId) {
        WebSocketServer target = users.get(toUserId);
        if (target != null) {
            User fromUser = userMapper.selectById(fromUserId);
            JSONObject message = new JSONObject();
            message.put("event", "game-invite");
            message.put("fromUserId", fromUserId);
            message.put("fromUsername", fromUser.getUsername());
            message.put("fromUserPhoto", fromUser.getPhoto());
            target.sendMessage(message.toJSONString());
        }
    }

    // 处理游戏邀请响应
    private void handleGameInviteResponse(JSONObject data) {
        Integer fromUserId = this.user.getId(); // 当前响应的用户
        Integer toUserId = data.getInteger("toUserId"); // 发出邀请的用户
        String response = data.getString("response"); // 接受或拒绝

        WebSocketServer inviter = users.get(toUserId);

        if (inviter != null) {
            JSONObject message = new JSONObject();
            message.put("event", "game-invite-result");
            message.put("fromUserId", fromUserId);
            message.put("fromUsername", this.user.getUsername());
            message.put("response", response);
            inviter.sendMessage(message.toJSONString());

            // 如果接受邀请，将双方加入匹配
            if ("accept".equals(response)) {
                // 添加邀请关系，方便匹配系统优先匹配
                MultiValueMap<String, String> inviteData = new LinkedMultiValueMap<>();
                inviteData.add("inviter_id", toUserId.toString());
                inviteData.add("invitee_id", fromUserId.toString());
                try {
                    restTemplate.postForObject("http://ball-matchingsystem:3001/player/invite/", inviteData, String.class);
                } catch (Exception e) {
                    log.error("添加邀请关系失败: " + e.getMessage());
                }

                // 用户1加入匹配池
                MultiValueMap<String, String> data1 = new LinkedMultiValueMap<>();
                data1.add("user_id", toUserId.toString());
                data1.add("rating", userMapper.selectById(toUserId).getRating().toString());
                restTemplate.postForObject(addPlayerUrl, data1, String.class);

                // 用户2加入匹配池
                MultiValueMap<String, String> data2 = new LinkedMultiValueMap<>();
                data2.add("user_id", fromUserId.toString());
                data2.add("rating", this.user.getRating().toString());
                restTemplate.postForObject(addPlayerUrl, data2, String.class);

                // 通知双方已加入匹配
                JSONObject matchingNotify = new JSONObject();
                matchingNotify.put("event", "matching-with-friend");
                matchingNotify.put("message", "已与好友加入匹配队列");

                if (inviter != null) {
                    inviter.sendMessage(matchingNotify.toJSONString());
                }
                this.sendMessage(matchingNotify.toJSONString());
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    public void sendMessage(String message) {
        if (this.session == null) {
            log.warn("尝试向未连接的会话发送消息");
            return;
        }

        synchronized (this.session) {
            try {
                if (this.session.isOpen()) {
                    this.session.getBasicRemote().sendText(message);
                } else {
                    log.warn("尝试向已关闭的会话发送消息");
                }
            } catch (IOException e) {
                log.error("发送消息出错: {}", e.getMessage());
            }
        }
    }
}
